package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.query.ReplyPageQuery;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.domain.vo.ReplyVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author lcm
 * @since 2023-07-26
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {

    private final IInteractionQuestionService iInteractionQuestionService;
    private final UserClient userClient;
    private final RabbitMqHelper mqHelper;

    @Override
    @Transactional
    public void addAnswerOrComment(ReplyDTO replyDTO) {
        //拷贝po
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        //获取用户id
        Long userId = UserContext.getUser();
        reply.setUserId(userId);
        save(reply);

        InteractionQuestion question = iInteractionQuestionService.lambdaQuery()
                .eq(InteractionQuestion::getId, reply.getQuestionId())
                .one();

        //判断是否是回答
        if(replyDTO.getAnswerId()== null){
            //回答
            //设置为已查看,设置最新的回答id
            question.setLatestAnswerId(replyDTO.getAnswerId());
            question.setAnswerTimes(question.getAnswerTimes()+1);
        }
        else{
            //评论
            //增加回答下评论数量
           int times=reply.getReplyTimes()==null?0: reply.getReplyTimes();
           reply.setReplyTimes(times+1);
        }
        Boolean isStudent = replyDTO.getIsStudent();
        //判断是不是学生提交
        if(isStudent){
            question.setStatus(QuestionStatus.UN_CHECK);
        }
        //新增至数据库
        iInteractionQuestionService.updateById(question);
        updateById(reply);

        //新增MQ发送消息至积分系统
        mqHelper.send(
                MqConstants.Exchange.LEARNING_EXCHANGE,
                MqConstants.Key.WRITE_REPLY,
                userId
        );
        log.info("用户：{}向积分服务发送，课程小节学习一小节",userId);

    }

    @Override
    public PageDTO<ReplyVO> pageComment(ReplyPageQuery replyPageQuery,boolean isAdmin) {

        //1.分页查询
        Long answerId = replyPageQuery.getAnswerId();
        Long questionId = replyPageQuery.getQuestionId();

        if (questionId == null && answerId == null) {
            throw new BadRequestException("问题或回答id不能都为空");
        }

        Page<InteractionReply> page = lambdaQuery()
                .eq(answerId != null, InteractionReply::getAnswerId, answerId)
                .eq(questionId != null, InteractionReply::getQuestionId, questionId)
                .eq(!isAdmin,InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPageDefaultSortByCreateTimeDesc());
        //健壮性处理
        List<InteractionReply> records = page.getRecords();
        if(CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //2.数据VO封装
        //2.1 用户信息
        Set<Long> userIds = records.stream()
                .filter(Predicate.not(InteractionReply::getAnonymity).or(r->isAdmin))
                .map(InteractionReply::getUserId)
                .collect(Collectors.toSet());

        Set<Long> targetReplyIds = records.stream()
                .map(InteractionReply::getTargetReplyId)
                .collect(Collectors.toSet());

        // 2.2.查询目标回复，如果目标回复不是匿名，则需要查询出目标回复的用户信息
        targetReplyIds.remove(0L);
        targetReplyIds.remove(null);
        if(targetReplyIds.size() > 0) {
            List<InteractionReply> targetReplies = listByIds(targetReplyIds);
            Set<Long> targetUserIds = targetReplies.stream()
                    .filter(Predicate.not(InteractionReply::getAnonymity).or(r->isAdmin))
                    .map(InteractionReply::getUserId)
                    .collect(Collectors.toSet());
            userIds.addAll(targetUserIds);
        }

        List<UserDTO> users = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));

        List<ReplyVO> voList = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            ReplyVO vo = BeanUtils.toBean(record, ReplyVO.class);
            voList.add(vo);
            //判断是否是匿名，匿名不返回用户信息
            if(!record.getAnonymity()||isAdmin){
                UserDTO user=userMap.get(record.getUserId());
                if(user != null){
                    vo.setUserName(user.getName());
                    vo.setUserIcon(user.getIcon());
                    vo.setUserType(user.getType());
                }

            }
            //如果存在评论的目标，则需要设置目标用户信息
            if(record.getTargetReplyId() !=null){
                UserDTO targetUser=userMap.get(record.getTargetUserId());
                if(targetUser != null){
                    vo.setTargetUserName(targetUser.getName());
                }
            }

        }

        return PageDTO.of(page,voList);
    }

    @Override
    @Transactional
    public void hiddenOrShow(Long id, Boolean hidden) {
        // 1.查询
        InteractionReply old = getById(id);
        if (old == null) {
            return;
        }

        // 2.隐藏回答
        InteractionReply reply = new InteractionReply();
        reply.setId(id);
        reply.setHidden(hidden);
        updateById(reply);

        // 3.隐藏评论，先判断是否是回答，回答才需要隐藏下属评论
        if (old.getAnswerId() != null && old.getAnswerId() != 0) {
            // 3.1.有answerId，说明自己是评论，无需处理
            return;
        }
        // 3.2.没有answerId，说明自己是回答，需要隐藏回答下的评论
        lambdaUpdate()
                .eq(InteractionReply::getId,id)
                .set(InteractionReply::getHidden,hidden)
                .update();
    }
}
